package com.common.util.groovy;

import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import groovy.lang.Script;
import org.apache.commons.collections.map.LRUMap;
import org.codehaus.groovy.control.CompilerConfiguration;

import java.util.Collections;
import java.util.Map;

/**
 * groovy脚本解析器
 */
public class GroovyParser {

    /** 锁资源 */
    private static final Object        LOCK        = new Object();

    /** GroovyShell */
    private static final GroovyShell shell;

    /** 解析器缓存 */
    private static Map<String, Script> cacheParser = Collections.synchronizedMap(new LRUMap(200));

    //初始化
    static {
        CompilerConfiguration cfg = new CompilerConfiguration();
        cfg.setScriptBaseClass(FunctionGroovyScript.class.getName());
        shell = new GroovyShell(cfg);
    }

    /**
     * 解析groovy脚本结果
     * 
     * @param expression            表达式
     * @return                      结果
     */
    public static String parse(String expression) {
        Script script = getScriptFromCache(expression);
        //加锁
        synchronized (LOCK) {
            //绑定
            script.setBinding(new Binding());
            //解析
            return String.valueOf(script.run());
        }
    }

    /**
     * 解析groovy脚本结果
     * 
     * @param expression            表达式
     * @param key                   上下文key
     * @param obj                   上下文
     * @return                      结果
     */
    public static String parse(String expression, String key, Object obj) {
        //上下文参数绑定
        Binding binding = new Binding();
        //设置属性
        binding.setProperty(key, obj);
        //获取Script
        Script script = getScriptFromCache(expression);
        //加锁
        synchronized (LOCK) {
            //绑定
            script.setBinding(binding);
            //解析
            return String.valueOf(script.run());
        }
    }

    /**
     * 解析groovy脚本结果
     * 
     * @param expression            表达式
     * @param context                   上下文
     * @return                      结果
     */
    public static String parse(String expression, Map<String, ?> context) {
        //上下文参数绑定
        Binding binding = new Binding();
        //设置属性
        for (Map.Entry<String, ?> e : context.entrySet()) {
            binding.setProperty(e.getKey(), e.getValue());
        }
        //获取Script
        Script script = getScriptFromCache(expression);
        //加锁
        synchronized (LOCK) {
            //绑定
            script.setBinding(binding);
            //解析
            return String.valueOf(script.run());
        }
    }

    /**
     * 执行脚本
     * @param expression
     * @param binding
     * @return
     */
    public static Object parse(String expression, Binding binding) {
        //获取Script
        Script script = getScriptFromCache(expression);
        //加锁
        synchronized (LOCK) {
            //绑定
            script.setBinding(binding);
            //解析
            return script.run();
        }
    }

    /**
     * 根据表达式获取Script
     * 
     * @param expression       groovy表达式
     * @return
     */
    private static Script getScriptFromCache(String expression) {
        if (cacheParser.containsKey(expression)) {
            return cacheParser.get(expression);
        }
        synchronized (LOCK) {
            if (cacheParser.containsKey(expression)) {
                return cacheParser.get(expression);
            }
            Script script = shell.parse(expression);
            cacheParser.put(expression, script);
            return script;
        }
    }

}
